package com.uatair.common.mqtt.uploader;

import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.uatair.common.mqtt.domain.dto.ApiUploadResponse;
import com.uatair.common.mqtt.domain.task.RecodeTask;
import com.uatair.common.mqtt.domain.task.SortieTask;
import com.uatair.common.mqtt.domain.task.TaskDTO;
import com.uatair.common.mqtt.util.AESUtil;
import com.uatair.common.mqtt.util.UAesUtil;
import org.apache.commons.codec.binary.Base64;
import org.json.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
public class AnhuiAgricultureTaskUploader {

    private static final Logger log = LoggerFactory.getLogger(AnhuiAgricultureTaskUploader.class);

    private static String APP_ID = "k2HCHT0m";

    private static String APP_SECRET = "a269e6361c545ee234317885515e1f2fc276dc00";

    private static final String BASE_URL = "http://47.100.69.152:10092/openApi/agricultural/";
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");


    public static void main(String[] args) {
//        getPlatformToken();
//        uploadTask();
    }

    public List<RecodeTask> putAnHuiTask(TaskDTO taskDTO){
        List<RecodeTask> recodeTaskList = new ArrayList<>();
        if (!taskDTO.getSortieTaskList().isEmpty()){
            RecodeTask recodeTask = uploadTask(taskDTO);
            ZhiBaoYunTaskUploader.setTaskId(taskDTO, recodeTaskList, recodeTask);
            for (SortieTask sortieTask : taskDTO.getSortieTaskList()) {
                RecodeTask recodeSorties = uploadSorties(sortieTask);
                ZhiBaoYunTaskUploader.setTaskId(taskDTO, recodeTaskList, recodeSorties);
            }
        }
        return recodeTaskList;
    }

    private RecodeTask uploadTask(TaskDTO taskDTO) {
        // 构建请求体
        JSONObject body = new JSONObject();
        body.put("deviceAlias", taskDTO.getUavTaskList().get(0).getSn());
        body.put("taskCode", taskDTO.getTaskId());
        body.put("workMode", 1);
        // 构建完整请求
        JSONObject request = new JSONObject();
        JSONObject header = new JSONObject();
        String requestTime = sdf.format(new Date());
        String serviceName = "uploadTask";

        header.put("appId", APP_ID);
        header.put("requestTime", requestTime);
        header.put("serviceName", serviceName);
        request.put("Header", header);
        request.put("Body", body);
        // 生成签名
        String sign = generateSign(request, APP_ID, serviceName, requestTime, APP_SECRET);
        header.put("sign", sign);
        // 发送请求
        try {
            String response = sendPostRequest(BASE_URL + "uploadTask", request.toString());
            System.out.println("Response: " + response);
            ApiUploadResponse apiUploadResponse = new ApiUploadResponse(null, response, BASE_URL + "uploadTask", 200);
            return ZhiBaoYunTaskUploader.getRecode(apiUploadResponse, new org.json.JSONObject(request.toJSONString()), "无人机任务推送");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public RecodeTask uploadSorties(SortieTask sortieTask) {
        try {
            // 1. 构建 Body 节点
            if (sortieTask.getGeoJson()!=null) {
                JSONObject polygon = getPolygon(sortieTask.getGeoJson());
                if (polygon.get("polygon")!=null) {
                    JSONObject bodyJson = new JSONObject();
                    bodyJson.put("taskCode", sortieTask.getTaskId());
                    bodyJson.put("sortieCode", sortieTask.getSortieNo());
                    bodyJson.put("deviceAlias", sortieTask.getSn());
                    bodyJson.put("center_lng", polygon.get("lng").toString());
                    bodyJson.put("center_lat", polygon.get("lat").toString());
                    bodyJson.put("takeoffTime", sortieTask.getStartTime().getTime());
                    bodyJson.put("landTime", sortieTask.getEndTime().getTime());
                    DecimalFormat df = new DecimalFormat("0.00");
                    bodyJson.put("workArea", df.format(sortieTask.getSize()*0.0015));
                    bodyJson.put("totalFlow", df.format(sortieTask.getDosage()/1000));
                    bodyJson.put("totalFlightTime", sortieTask.getFlightTime()/1000);
                    bodyJson.put("pathData", polygon);
                    // 构建完整请求
                    JSONObject request = new JSONObject();
                    JSONObject header = new JSONObject();
                    String requestTime = sdf.format(new Date());
                    String serviceName = "uploadSorties";
                    header.put("appId", APP_ID);
                    header.put("requestTime", requestTime);
                    header.put("serviceName", serviceName);
                    request.put("Header", header);
                    request.put("Body", bodyJson);
                    // 生成签名
                    String sign = generateSign(request, APP_ID, serviceName, requestTime, APP_SECRET);
                    header.put("sign", sign);
                    String response = sendPostRequest(BASE_URL + "uploadSorties", request.toString());
                    ApiUploadResponse apiUploadResponse = new ApiUploadResponse(null, response, BASE_URL + "uploadSorties", 200);
                    return ZhiBaoYunTaskUploader.getRecode(apiUploadResponse, new org.json.JSONObject(request.toJSONString()), "无人机基本信息上报");
                }
            }
        } catch (Exception e) {
            log.error("架次推送失败: ", e);
        }
        return null;
    }

    public RecodeTask uploadTrace(SortieTask sortieTask) {
        try {
            if (sortieTask.getPath()!=null) {
                List<String> strings = UAesUtil.downloadAndParseFile(sortieTask.getPath());
                if (!strings.isEmpty()) {
                    JSONObject bodyJson = new JSONObject();
                    bodyJson.put("taskCode", sortieTask.getTaskId());
                    bodyJson.put("sortieCode", sortieTask.getSortieNo());
                    bodyJson.put("deviceAlias", sortieTask.getSn());
                    List<org.json.JSONObject> traceJson = AESUtil.getJsonObjects(strings);
                    long startMillis = sortieTask.getStartTime().toInstant().toEpochMilli();
                    long endMillis = sortieTask.getEndTime().toInstant().toEpochMilli();
                    long totalMillis = endMillis - startMillis;
                    double intervalMillis = (double) totalMillis / ((traceJson.size()==1?2:traceJson.size()) - 1);
                    JSONArray trackInfoList = new JSONArray();
                    // 1. 构建 Body 节点
                    for (int i = 0; i < traceJson.size(); i++) {
                        org.json.JSONObject osd = traceJson.get(i);
                        JSONObject trackInfo = new JSONObject();
                        // 计算当前时间点
                        long currentMillis;
                        if (i == traceJson.size() - 1) {
                            // 最后一个点直接使用结束时间，避免浮点误差
                            currentMillis = endMillis;
                        } else {
                            // 使用四舍五入来减少累积误差
                            currentMillis = startMillis + Math.round(i * intervalMillis);
                        }
                        trackInfo.put("trajectoryId", String.valueOf(currentMillis));
                        trackInfo.put("reportTime", currentMillis);
                        trackInfo.put("longitude", osd.get("lon"));
                        trackInfo.put("latitude", osd.get("lat"));
                        trackInfo.put("sprayStatus", 0);
                        trackInfo.put("flowRate", osd.get("flow"));
                        trackInfo.put("rowGap", 0);
                        double vx = osd.getDouble("vx");
                        double vy = osd.getDouble("vy");
                        double vz = osd.getDouble("vz");
                        double v = UAesUtil.calculateSpeedFromComponents(vx,vy,vz);
                        DecimalFormat df = new DecimalFormat("#.##");
                        trackInfo.put("speed", df.format(v * 3.6));
                        trackInfo.put("height", osd.get("relativeAlt"));
                        trackInfo.put("altitude", osd.get("alt"));
                        trackInfo.put("row", osd.get("heading"));
                        trackInfo.put("uavStatus", 0);
                        trackInfoList.put(trackInfo);
                    }
                    bodyJson.put("trackInfo",trackInfoList);
                    // 构建完整请求
                    JSONObject request = new JSONObject();
                    JSONObject header = new JSONObject();
                    String requestTime = sdf.format(new Date());
                    String serviceName = "uploadLocation";
                    header.put("appId", APP_ID);
                    header.put("requestTime", requestTime);
                    header.put("serviceName", serviceName);
                    request.put("Header", header);
                    request.put("Body", bodyJson);
                    // 生成签名
                    String sign = generateSign(request, APP_ID, serviceName, requestTime, APP_SECRET);
                    header.put("sign", sign);
                    String response = sendPostRequest(BASE_URL + "uploadLocation", request.toString());
                    ApiUploadResponse apiUploadResponse = new ApiUploadResponse(null, response, BASE_URL + "uploadLocation", 200);
                    return ZhiBaoYunTaskUploader.getRecode(apiUploadResponse, new org.json.JSONObject(request.toJSONString()), "无人机轨迹上报");
                }
            }
        } catch (Exception e) {
            log.error("轨迹推送失败: ", e);
        }
        return null;
    }

    private JSONObject getPolygon(String geoJson) {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode root = null;
        try {
            root = mapper.readTree(geoJson);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

        JsonNode features = root.get("features");
        List<double[]> points = new ArrayList<>();
        if (features.isArray()) {
            for (JsonNode feature : features) {
                if ("land".equals(feature.get("id").asText())) {
                    // 提取coordinates
                    JsonNode coordsNode = feature.get("geometry").get("coordinates").get(0);
                    if (coordsNode.isArray()) {
                        for (JsonNode coordNode : coordsNode) {
                            double lng = coordNode.get(0).asDouble(); // 经度
                            double lat = coordNode.get(1).asDouble(); // 纬度
                            points.add(new double[]{lng, lat});
                        }
                    }
                }
            }
        }
        // 1. 生成闭合 Polygon 字符串
        StringBuilder polygonStr = new StringBuilder("POLYGON ((");
        for (double[] point : points) {
            polygonStr.append(point[0]).append(" ").append(point[1]).append(", ");
        }
        JSONObject request = new JSONObject();
        if (!points.isEmpty()) {
            // 闭合 Polygon（添加第一个点）
            polygonStr.append(points.get(0)[0]).append(" ").append(points.get(0)[1]).append("))");
            // 2. 计算中心点（质心）
            double[] center = calculatePolygonCenter(points);
            request.put("polygon", polygonStr.toString());
            request.put("lng", center[0]);
            request.put("lat", center[1]);
        } else {
            request.put("polygon", null);
        }
        log.info("解析地块：{}", request);
        return request;
    }

    /**
     * 计算多边形的质心（简单平均法，适用于小区域）
     */
    private static double[] calculatePolygonCenter(List<double[]> points) {
        double sumLng = 0, sumLat = 0;
        for (double[] point : points) {
            sumLng += point[0];
            sumLat += point[1];
        }
        return new double[]{
                sumLng / points.size(),
                sumLat / points.size()
        };
    }

    private static String generateSign(JSONObject request, String appId, String serviceName,
                                       String requestTime, String appSecret) {
        // 提取Body部分并转换为JSON字符串
        String bodyJson = JSON.toJSONString(request.getJSONObject("Body"));

        // 构建带Body节点的字符串
        String bodyWithNode = "\"Body\":" + bodyJson;
        System.out.println("bodyWithNode:"+bodyWithNode);
        // Base64编码
        String data = Base64.encodeBase64String(bodyWithNode.getBytes(StandardCharsets.UTF_8));
        System.out.println("data="+data);
        // 拼接签名字符串
        String strText = appId + serviceName + requestTime + data + appSecret;
        System.out.println("strText="+strText);
        // 生成MD5并转为大写
        String md5string = SecureUtil.md5(strText).toUpperCase();
        System.out.println("md5string="+md5string);
        return md5string;
    }

    private static String sendPostRequest(String urlString, String jsonInput) throws Exception {
        URL url = new URL(urlString);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setDoOutput(true);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/json");

        OutputStream os = conn.getOutputStream();
        os.write(jsonInput.getBytes());
        os.flush();

        if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
            throw new RuntimeException("Failed : HTTP error code : " + conn.getResponseCode());
        }

        java.util.Scanner scanner = new java.util.Scanner(conn.getInputStream()).useDelimiter("\\A");
        return scanner.hasNext() ? scanner.next() : "";
    }
}
